/* AccountsManager.java
 *
 * Copyright 2011-2012 Aleksey Konovalov, r.u.s.h.a.n.
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 * 
 */

package org.jimm.protocol;

import java.util.HashMap;

import android.content.ContentResolver;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Handler;
import android.util.Log;

import org.jimm.db.JimmDatabase.Accounts;
import org.jimm.protocol.icq.Icq;
import org.jimm.service.Preferences;

/**
 * @author Aleksey Konovalov, r.u.s.h.a.n.
 */
public class AccountsManager extends ContentObserver {

    private static final String LOG_TAG = "Jimm:AccountsManager";

    private HashMap<String, Protocol> protocols = new HashMap<String, Protocol>();
    private ContentResolver contentResolver;
    private Preferences p = null;

    public AccountsManager(ContentResolver contentResolver, Preferences preferences) {
        super(new Handler());
        this.p = preferences;
        this.contentResolver = contentResolver;
        contentResolver.registerContentObserver(Accounts.CONTENT_URI, true, this);
        updateFromBD();
    }

    @Override
    public void onChange(boolean selfChange) {
        updateFromBD();
    }

    private int getRealType(int type) {
        switch (type) {
            case Accounts.PROTOCOL_GTALK:
            case Accounts.PROTOCOL_FACEBOOK:
            case Accounts.PROTOCOL_LJ:
            case Accounts.PROTOCOL_YANDEX:
            case Accounts.PROTOCOL_VK:
            case Accounts.PROTOCOL_QIP:
            case Accounts.PROTOCOL_ODNOKLASSNIKI:
                return Accounts.PROTOCOL_JABBER;
        }
        return type;
    }

    private void updateFromBD() {
        Log.i(LOG_TAG, "updateFromBD()");
        Cursor c = contentResolver.query(Accounts.CONTENT_URI, null, null, null, null);
        HashMap<String, Protocol> tmp = new HashMap<String, Protocol>();
        synchronized (this) {
            if (c.moveToFirst()) {
                do {
                    String login = c.getString(c.getColumnIndex(Accounts.LOGIN));
                    Protocol protocol = protocols.get(login);


                    if (protocol == null) {
                        switch (getRealType(c.getInt(c.getColumnIndex(Accounts.TYPE)))) {
                            case Accounts.PROTOCOL_ICQ:
                                protocol = new Icq();
                                break;
                            case Accounts.PROTOCOL_JABBER:
                                break;
                        }
                        Profile profile = new Profile();

                        profile.userId = c.getString(c.getColumnIndex(Accounts.LOGIN));
                        profile.password = c.getString(c.getColumnIndex(Accounts.PASSWORD));
                        profile.nick = c.getString(c.getColumnIndex(Accounts.NICK));
                        profile.statusIndex = c.getInt(c.getColumnIndex(Accounts.STATUS_INDEX));
                        profile.statusMessage = c.getString(c.getColumnIndex(Accounts.STATUS_MESSAGE));
                        profile.protocolType = c.getInt(c.getColumnIndex(Accounts.TYPE));
                        profile.isActive = ((c.getInt(c.getColumnIndex(Accounts.FLAGS)) & Accounts.FLAG_ACTIVE) != 0);
                        profile.autoConnect = ((c.getInt(c.getColumnIndex(Accounts.FLAGS)) & Accounts.FLAG_AUTOCONNECT) != 0);
                        if (!profile.isActive) continue;


                        protocol.setProfile(profile);
                        protocol.init(p);

                        if (profile.autoConnect)
                            protocol.connect();
                    }
                    tmp.put(login, protocol);
                } while (c.moveToNext());
            }
            protocols = tmp;
        }
        c.close();
    }

    public synchronized boolean isConnecting() {
        for (Protocol p : protocols.values()) {
            if (p.isConnecting()) return true;
        }
        return false;
    }

    public synchronized boolean isConnected() {
        for (Protocol p : protocols.values()) {
            if (!p.isConnected()) return false;
        }
        return true;
    }

    public synchronized Protocol getProtocol(String accountId) {
        return protocols.get(accountId);
    }

    public synchronized Protocol getProtocol(Cursor account) {
        String accountId = account.getString(account.getColumnIndex(Accounts.LOGIN));
        return getProtocol(accountId);
    }

    /**
     * @param n Поряковый номер аккаунта
     */
    public synchronized Protocol getProtocol(int n) {
        return (Protocol) protocols.values().toArray()[n];
    }

    public synchronized Protocol getProtocol(Contact c) {
        for (int i = 0; i < getCount(); ++i) {
            if (getProtocol(i).inContactList(c)) {
                return getProtocol(i);
            }
        }
        return null;
    }

    public synchronized int getCount() {
        return protocols.size();
    }

    public synchronized void connectAll() {
        for (Protocol p : protocols.values()) {
            if (!p.isConnected()) p.connect();
        }
    }

    public synchronized void disconnectAll() {
        for (Protocol p : protocols.values()) {
            if (p.isConnected()) p.disconnect();
        }
    }

    public synchronized void setStatus(int statusIndex, String msg) {
        for (Protocol p : protocols.values()) {
            p.setOnlineStatus(statusIndex, msg);
        }
    }

    public synchronized void setXStatus(int xstatus, String title, String desc) {
        for (Protocol p : protocols.values()) {
            p.setXStatus(xstatus, title, desc);
        }
    }

    public void setPrivateStatus(int position) {
        for (Protocol p : protocols.values()) {
            p.setPrivateStatus(position);
        }
    }

    public void setProtocolListener(ProtocolListener l) {
        for (Protocol p : protocols.values()) {
            p.setProtocolListener(l);
        }
    }

    public int getUnreadMessageCount() {
        int count = 0;
        for (Protocol p : protocols.values()) {
            count += p.getUnreadMessageCount();
        }

        return count;
    }

    public int getOnlineProtocolCount() {
        int count = 0;
        for (Protocol p : protocols.values()) {
            if (p.isConnected())
                count++;
        }

        return count;
    }

    public String[] getOnlineProtocolList() {
        int i = 0;
        String[] _protocols = new String[getOnlineProtocolCount()];

        for (Protocol p : protocols.values()) {
            if (p.isConnected()) {
                _protocols[i] = p.getNick();
                i++;
            }
        }

        return _protocols;
    }
}
